/**
 * @p.md
 * 
 * 持久化工厂类，用于创建持久化组件
 */
import { ActorSystem } from '../actor/actorSystem';
import { Actor } from '../actor/actor';
import { PID } from '../actor/pid';
import { Props } from '../actor/props';
import { PersistenceProvider } from './persistenceProvider';
import { InMemoryProvider } from './inMemoryProvider';
import { FileSystemProvider } from './fileSystemProvider';
import { WasmPersistenceProvider } from './wasmPersistenceProvider';
import { DefaultPersistentContext, DefaultRecoverContext, DefaultCommandContext } from './persistentContext';
import { PersistentActor } from './persistentActor';
import { EventType } from './persistent';
import { WasmBridge } from '../wasm/wasmBridge';
import { SQLiteProvider } from './sqliteProvider';
import { MongoDBProvider } from './mongoDBProvider';
import { PostgreSQLProvider } from './postgreSQLProvider';
import { BunSQLiteProvider } from './bunSqliteProvider';

/**
 * 恢复策略枚举
 */
export enum RecoveryStrategy {
  /**
   * 先恢复快照然后恢复事件
   */
  SnapshotThenEvents,
  
  /**
   * 只恢复事件
   */
  EventsOnly,
  
  /**
   * 只恢复快照
   */
  SnapshotOnly
}

/**
 * 持久化 Props 配置
 */
export interface PersistenceConfig {
  /**
   * 恢复策略
   */
  recoveryStrategy: RecoveryStrategy;
  
  /**
   * 快照间隔 (事件数量)
   */
  snapshotInterval: number;
  
  /**
   * 事件批处理大小
   */
  eventsBatchSize: number;
}

/**
 * 持久化工厂类
 */
export class PersistenceFactory {
  private static instance: PersistenceFactory;
  private providers: Map<string, PersistenceProvider> = new Map();
  private defaultConfig: PersistenceConfig = {
    recoveryStrategy: RecoveryStrategy.SnapshotThenEvents,
    snapshotInterval: 100,
    eventsBatchSize: 50
  };

  /**
   * 获取单例实例
   */
  public static getInstance(): PersistenceFactory {
    if (!PersistenceFactory.instance) {
      PersistenceFactory.instance = new PersistenceFactory();
    }
    return PersistenceFactory.instance;
  }

  /**
   * 私有构造函数
   */
  private constructor() {}

  /**
   * 注册持久化提供者
   * @param name 提供者名称
   * @param provider 提供者实例
   */
  public registerProvider(name: string, provider: PersistenceProvider): void {
    this.providers.set(name, provider);
  }

  /**
   * 获取持久化提供者
   * @param name 提供者名称，默认为 'default'
   * @returns 持久化提供者实例
   */
  public getProvider(name: string = 'default'): PersistenceProvider {
    const provider = this.providers.get(name);
    if (!provider) {
      throw new Error(`PersistenceProvider '${name}' not found`);
    }
    return provider;
  }

  /**
   * 创建基于内存的持久化提供者
   * @param name 提供者名称，默认为 'default'
   * @returns 内存持久化提供者
   */
  public createInMemoryProvider(name: string = 'default'): InMemoryProvider {
    const provider = new InMemoryProvider();
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建基于文件系统的持久化提供者
   * @param basePath 基础路径
   * @param name 提供者名称，默认为 'file'
   * @returns 文件系统持久化提供者
   */
  public createFileSystemProvider(basePath: string = './persistence', name: string = 'file'): FileSystemProvider {
    const provider = new FileSystemProvider(basePath);
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建 SQLite 持久化提供者
   * @param dbPath 数据库文件路径
   * @param name 提供者名称
   * @returns SQLiteProvider 实例
   */
  public createSQLiteProvider(dbPath: string = './persistence/protoactor.db', name: string = 'sqlite'): SQLiteProvider {
    const provider = new SQLiteProvider(dbPath);
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建 PostgreSQL 持久化提供者
   * @param connectionString PostgreSQL 连接字符串
   * @param name 提供者名称
   * @returns PostgreSQLProvider 实例
   */
  public createPostgreSQLProvider(
    connectionString: string = 'postgresql://postgres:postgres@localhost:5432/protoactor',
    name: string = 'postgresql'
  ): PostgreSQLProvider {
    const provider = new PostgreSQLProvider(connectionString);
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建 MongoDB 持久化提供者
   * @param connectionString MongoDB 连接字符串
   * @param dbName 数据库名称
   * @param name 提供者名称
   * @returns MongoDBProvider 实例
   */
  public createMongoDBProvider(
    connectionString: string = 'mongodb://localhost:27017',
    dbName: string = 'protoactor',
    name: string = 'mongodb'
  ): MongoDBProvider {
    const provider = new MongoDBProvider(connectionString, dbName);
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建基于 WASM 的持久化提供者
   * @param wasmBridge WASM 桥接器
   * @param name 提供者名称，默认为 'wasm'
   * @returns WASM 持久化提供者
   */
  public createWasmProvider(wasmBridge: WasmBridge, name: string = 'wasm'): WasmPersistenceProvider {
    const provider = new WasmPersistenceProvider(wasmBridge);
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建 Bun SQLite 持久化提供者
   * @param dbPath 数据库文件路径
   * @param name 提供者名称
   * @returns BunSQLiteProvider 实例
   */
  public createBunSQLiteProvider(dbPath: string = './persistence/protoactor.db', name: string = 'bun-sqlite'): BunSQLiteProvider {
    const provider = new BunSQLiteProvider(dbPath);
    this.registerProvider(name, provider);
    return provider;
  }

  /**
   * 创建持久化 Actor Props
   * @param actorCreator 持久化 Actor 创建函数
   * @param providerName 持久化提供者名称，默认为 'default'
   * @param config 持久化配置
   * @returns Actor 属性
   */
  public persistentProps(
    actorCreator: () => PersistentActor, 
    providerName: string = 'default',
    config?: Partial<PersistenceConfig>
  ): Props {
    // 合并配置
    const finalConfig = { ...this.defaultConfig, ...config };
    
    // 创建 Producer 函数，用于启动持久化流程
    const producer = () => {
      const actor = actorCreator();
      // 这里应该为 actor 设置持久化相关的初始状态
      // 在实际应用中，我们会将 actor 包装在一个持久化处理器中
      return actor;
    };
    
    // 使用 Props.fromProducer 创建基本 Props
    return Props.fromProducer(producer);
  }

  /**
   * 创建默认持久化上下文
   * @param actorSystem Actor 系统
   * @param persistenceId 持久化 ID
   * @param actor Actor 实例
   * @param self Actor 的 PID
   * @param message 消息
   * @param providerName 持久化提供者名称，默认为 'default'
   * @returns 持久化上下文
   */
  public createContext(
    actorSystem: ActorSystem,
    persistenceId: string,
    actor: Actor,
    self: PID,
    message: any,
    providerName: string = 'default'
  ): DefaultPersistentContext {
    const provider = this.getProvider(providerName);
    return new DefaultPersistentContext(
      actorSystem,
      provider,
      persistenceId,
      actor,
      self,
      message
    );
  }

  /**
   * 创建恢复上下文
   * @param actorSystem Actor 系统
   * @param persistenceId 持久化 ID
   * @param actor Actor 实例
   * @param self Actor 的 PID
   * @param event 事件数据
   * @param eventType 事件类型
   * @param eventIndex 事件索引
   * @param providerName 持久化提供者名称，默认为 'default'
   * @returns 恢复上下文
   */
  public createRecoverContext(
    actorSystem: ActorSystem,
    persistenceId: string,
    actor: Actor,
    self: PID,
    event: any,
    eventType: EventType,
    eventIndex: number,
    providerName: string = 'default'
  ): DefaultRecoverContext {
    const provider = this.getProvider(providerName);
    return new DefaultRecoverContext(
      actorSystem,
      provider,
      persistenceId,
      actor,
      self,
      event,
      eventType,
      eventIndex
    );
  }

  /**
   * 创建命令上下文
   * @param actorSystem Actor 系统
   * @param persistenceId 持久化 ID
   * @param actor Actor 实例
   * @param self Actor 的 PID
   * @param message 消息
   * @param index 当前索引
   * @param providerName 持久化提供者名称，默认为 'default'
   * @returns 命令上下文
   */
  public createCommandContext(
    actorSystem: ActorSystem,
    persistenceId: string,
    actor: Actor,
    self: PID,
    message: any,
    index: number,
    providerName: string = 'default'
  ): DefaultCommandContext {
    const provider = this.getProvider(providerName);
    return new DefaultCommandContext(
      actorSystem,
      provider,
      persistenceId,
      actor,
      self,
      message,
      index
    );
  }
} 